	import flash.events.NetStatusEvent;
	import flash.events.TimerEvent;
	import flash.external.*;
	import flash.net.SharedObject;
	import flash.utils.Timer;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	import mx.core.Application;
	import mx.core.SoundAsset;
	import mx.effects.easing.*;
	import mx.managers.PopUpManager;
	import mx.utils.Base64Encoder;
	import mx.validators.Validator; 

	include "tools.as";

	[Bindable]
       [Embed(source="assets/male.png")]
       public var maleIcon:Class;
	[Bindable]
       [Embed(source="assets/maleBusy.png")]
       public var maleBusyIcon:Class;
       
	[Bindable]
       [Embed(source="assets/mail32.png")]
       public var mailIcon:Class;
	[Bindable]
       [Embed(source="assets/webcam32.png")]
       public var webcamIcon:Class;

	[Bindable]
       [Embed(source="assets/female.png")]
       public var femaleIcon:Class;
	[Bindable]
       [Embed(source="assets/femaleBusy.png")]
       public var femaleBusyIcon:Class; 
            
	[Bindable]
       [Embed(source="assets/couple.png")]
       public var coupleIcon:Class;
	[Bindable]
      [Embed(source="assets/coupleBusy.png")]
       public var coupleBusyIcon:Class; 
                        
	[Bindable]
       [Embed(source="assets/admin.png")]
       public var adminIcon:Class; 
	[Bindable]
		[Embed('assets/beep.mp3')]
       private var beepMP3:Class;
           
	[Bindable]
	[Embed('assets/dink.mp3')]
       private var dinkMP3:Class;            
            
    [Bindable]
    [Embed(source="assets/error.png")]
    public var errorIcon:Class;
           
    [Bindable]
    [Embed(source="assets/info.png")]
    public var infoIcon:Class;            
           
	private var ding:SoundAsset = new dinkMP3() as SoundAsset;
	private var beep:SoundAsset = new beepMP3() as SoundAsset;

	NetConnection.defaultObjectEncoding = flash.net.ObjectEncoding.AMF3;
	SharedObject.defaultObjectEncoding  = flash.net.ObjectEncoding.AMF3;
			

	
    public var nc:NetConnection;
    
            [Bindable] public var myuser:User;			
			[Bindable] public var myParameters:Object = new  Object();					
            
            public var so_chat:SharedObject;
            public var camera:Camera;
            public var camDetected:Boolean;
       		public var mic:Microphone;
            public var nsInGoing:NetStream
            public var nsOutGoing:NetStream;
            public var timerDrawMic:Timer = new Timer(200);
                        
            public var hisVideo:Video;
			public var myConfig:MyConfig = new MyConfig();		
			
			[Bindable] public var users:ArrayCollection=new ArrayCollection();
			[Bindable] public var rooms_dp:ArrayCollection=new ArrayCollection();
			[Bindable] public var types_dp:ArrayCollection=new ArrayCollection();
			[Bindable] public var lang:Object=new Object();			
			//[Bindable] public var myChat:Object=new  Object();
            
	
		
private function getTraductions(langue:String):void {
	myConfig.gateway.call("tv.getTraductions", new Responder(onResult,null), langue);
    function onResult ( result : Object ) : void {
		lang = result;
    }
    
}
private function fillTypes():void {
	myConfig.gateway.call("tv.getTypes", new Responder(onResult,null));
    function onResult ( result : Array ) : void {
		types_dp.source=result;
    }
}
public function debug(s:String):void {
	chat_text.htmlText+=s+"<br>";
}

public function getUserByUsername(username:String):Object {
	var anuser:Object =new Object();
	for (var i:int=0;i<users.length;i++)	{
		anuser = (users.getItemAt(i));
		if (anuser.username==username) return anuser;
     }	
     return null;
}

private function getUserIndex(username:String):int {
	for (var i:int=0;i<users.length;i++)	{
		if (users.getItemAt(i).username==username) return i;
     }	
     return -1;
}


public function enableGUI():void {
	Application.application.alpha=1;
}
            
public function disableGUI():void {
	Application.application.alpha=0.5;
}

		
public function netStatusHandler(event:NetStatusEvent):void {
	camDetected=false;
	debug(event.info.code);
    switch (event.info.code) {
	case "NetConnection.Connect.Success":
    	prepareStreams();
        break;
		default:
			nc.close();
			currentState="register";
			break;
      }
}
public function joinNewUser(newUser:Object):void {
	addUser(newUser.id , newUser.username , newUser.sex , newUser.online , newUser.webcam , newUser.room);
}
public function removeUser(id:int , username:String):void {
	var anUser : Object = getUserByUsername(username);
	if (!anUser) return;

	var index:int = getUserIndex(username); 
	if (myuser.room == username) {
		Alert.show(lang.OwnerLeft);
		nc.close();
	}
	if (index==-1) return;
	users.removeItemAt(index);
	return;
}

public function paramWebcam():void {
	Security.showSettings(SecurityPanel.DEFAULT);
}


public function getUserList(msg:Object):void {
	var i:String , id:int , username:String , sex:String , webcam:Boolean , online:Boolean , room:String;
	for (i in msg) {
		id = msg[i].id;
		username = msg[i].username;
		sex = msg[i].sex;
		webcam = msg[i].webcam;
		online = msg[i].online;
		room = msg[i].room; 
		addUser(id , username , sex , webcam , online , room);
	}		
	if ((!myuser.isAdmin ) && (users.length>MyConfig.maxUsers)) {
		Alert.show(lang.maxUsersReached);
    	nc.close();
	   	return;
	}	
}		


public function receiveText(username:String, msg:String, color:uint):void {
	chat_text.htmlText+='<b>'+myuser.username+'</b>:<font color="#'+rgbToHex(color)+'">'+ msg + '</font><br>';
	chat_text.validateNow();
	chat_text.verticalScrollPosition = chat_text.maxVerticalScrollPosition;
}
public function showUpdate():void {
	var myupdate:MyUpdate = new MyUpdate();
	PopUpManager.addPopUp(myupdate,titlewindow1,true);
	PopUpManager.centerPopUp(myupdate);
	
}
public function showMyScript():void {
	var win:MyScript = new MyScript();
	PopUpManager.addPopUp(win,titlewindow1,true);
	PopUpManager.centerPopUp(win);
	
}

public function sendText():void {
	var msg:String = text_txt.text;
	if (msg=="") return;
	text_txt.text="";
	so_chat.send("receiveText" , myuser.username , msg , color_picker.value);	
}
public function streamStatus(e:NetStatusEvent):void {	
	if (e.info.code.toString()=="NetStream.Play.Start") {
		if (e.info.details==myuser.username) {
			// do not play sound on ourselves !
			var volumeVideoTransform:SoundTransform = new SoundTransform();
			volumeVideoTransform.volume = 0;
			e.target.soundTransform = volumeVideoTransform;
		}
	} 
}

public function playAdmin(sound:Boolean = true):void {
	hisVideo = new Video( MyConfig.CAMERA_WIDTH , MyConfig.CAMERA_HEIGHT );
	nsInGoing = new NetStream(nc);	
	nsInGoing.client = this;
	nsInGoing.addEventListener(NetStatusEvent.NET_STATUS , streamStatus);
	hisWebcam.video = hisVideo;
	hisVideo.attachNetStream(nsInGoing);
	nsInGoing.play(myuser.room);
	
}

public function prepareStreams():void {		
	playAdmin();
	if (myuser.room!=myuser.username) {
		playAdmin();
		return;
	}	
			
	nsOutGoing = new NetStream(nc); 	
	camera = Camera.getCamera();
	if (camera!=null) {
		if (camera.muted) {
			paramWebcam();
		}				
		camera.setMode(MyConfig.CAMERA_WIDTH , MyConfig.CAMERA_HEIGHT , MyConfig.CAMERA_FPS);
		camera.setQuality(MyConfig.BW,MyConfig.QAULITY);
		camera.setKeyFrameInterval(MyConfig.CAMERA_KEYFRAME);			

		myWebcam.attachCamera(camera);
		nsOutGoing.attachCamera(camera);
	}	

	mic=Microphone.getMicrophone(0);
	if(mic!=null) {
		debug("micro detected");
		mic.setUseEchoSuppression(true);
		mic.rate=22;
       	var timer:Timer=new Timer(50);
		timer.addEventListener(TimerEvent.TIMER, drawMicLevel);
		timer.start();
		nsOutGoing.attachAudio(mic);
	}
}          

public function onNetSTatus(e:NetStatusEvent):void{
	debug(e.info.code);	
}

public function IhaveBeenKicked(username:String):void {
	if (myuser.username!=username) return;
	Alert.show(lang.msg_kicked);
	nc.close();currentState="register";
}
public function IhaveBeenBanned(username:String):void {
	if (myuser.username!=username) return;
	myConfig.gateway.call("tv.banUser", new Responder(onResult,null), username);
    function onResult ( result : Object ) : void {
		Alert.show(lang.msg_banned);
		nc.close();
		currentState="register";	
    }
}


public function kick(who:String):void {
	so_chat.send("IhaveBeenKicked",who);
}
public function ban(who:String):void {
	so_chat.send("IhaveBeenBanned",who);
}


private function drawMicLevel(evt:TimerEvent):void {
	micLevel.setProgress(mic.activityLevel,100);
}

public function forgotten():void {
	var validators:Array = Validator.validateAll([forgotten_emailV]);
	if(validators.length>0) {
		return;
	}
	myConfig.gateway.call("tv.forgotten", new Responder(onResult,null),forgotten_email.text);
    function onResult ( result : Object ) : void {
    		Alert.show(result.msg);
    		if (result.ok =="1") currentState = "register";
    		
			
		}			
	
}
public function register():void {
	var validators:Array = Validator.validateAll([creation_nameV , creation_emailV , creation_passwordV , creation_password2V, creation_channel_nameV]);
	if(validators.length>0) {
		return;
	}		
	if (creation_password.text != creation_password2.text) {
		Alert.show(lang.passwordDoNotMatch);
		return;
	}

	var sex:String = "m";
			
	myConfig.gateway.call("tv.register", new Responder(onResult,null),
	creation_name.text , sex , creation_email.text , creation_password.text, creation_channel_name.text, creation_channel_description.text, creation_channel_type.selectedItem.data);
    function onResult ( result : Object ) : void {
		if (result.ok==0) {
			Alert.show(result.msg);
			return
		}
		// c'est BON : screen shot ! ! !
		Alert.show(result.msg);			
		currentState="";
		email_txt.text = creation_email.text;
		password_txt.text =  creation_password.text;
		
    }

}
	 
public function onPlayStatus(info:Object):void {
	 }


public function filterBadWords(txt:String):String {
	var results:Array = txt.split("/\w+/g"); // results == ["","b"]
	return txt;

}

public function treat_text(txt:String,color:uint,username:String):String {
	if (myParameters.filterBadWords == 1) {
		txt = filterTxt(txt);
	}
	
	txt=hiliteURLs(txt);
	txt=filterTxt(txt);
	txt="<b>"+username+": </b><font color='#"+rgbToHex(color) +"'>"+txt+"</font><br>";
	return txt;
	
}
public function sendTextPrivate(texte:String,color:uint,username:String):void {
	texte = treat_text(texte,color,username);
	so_chat.send("receivePrivateMsg", myuser.username, username , texte);
}
public function sendTextPublic(texte:String , color:uint , username:String , room:String):void {
	texte = treat_text(texte,color,username);
	so_chat.send("receivePublicMsg", myuser.username , texte , room);
}
public function setOnline():void {
	var onLine:int=0; 
	if (start_btn.selected) {
		start_btn.label = lang.onAir;
		onLine = 1;
		setTimeout(takeSnapShot , MyConfig.TIMER);
	} else {
		start_btn.label = lang.notOnAir;
	}
	
	myConfig.gateway.call("tv.setOnline", new Responder(onResult,null) , myuser.username , onLine);
    function onResult ( result : Object ) : void {	
    }
    if (onLine==1) {
    	if (!record_checkbox.selected) {
    		nsOutGoing.publish(myuser.room);
    		playAdmin(false);
    	} else {
    		//nsOutGoing.publish(myuser.room,"record");
    	}	
    	return;
    } 
    if (onLine==0) {
    	nsOutGoing.close();
    	return;    	
    }
	
	
}

public function logout():void {
	if (nc!=null) {nc.close();}	
	currentState="";
}

public function loginAs():void {
  	nc=new NetConnection();			
	nc.client=this;
	var s:String = MyConfig.server + myuser.room;
	if (myuser.username == myuser.room) myuser.isAdmin = true;

	nc.connect(s , myuser.id , myuser.username , myuser.sex , myuser.online , myuser.webcam , myuser.room);
	nc.addEventListener(NetStatusEvent.NET_STATUS , netStatusHandler);
	
	so_chat = SharedObject.getRemote(myuser.room , nc.uri,false);
	so_chat.client = this; // refers to the scope of application and public funtions
	so_chat.addEventListener(SyncEvent.SYNC, OnSync);
	so_chat.connect(nc);	
}


public function takeSnapShot():void {
	if (camera==null || camera.muted) return;

	var matrix:Matrix = new Matrix();
	matrix.scale(0.5 , 0.5);
	var imageBitmapData:BitmapData = new BitmapData( 160 , 120 );
	imageBitmapData.draw(myWebcam,matrix);
	var bytes:ByteArray = new JPEGEncoder(90).encode(imageBitmapData);	
	var b64encoder:Base64Encoder = new Base64Encoder();
	b64encoder.encodeBytes(bytes);
	myConfig.gateway.call("tv.saveBitmap", new Responder(onResult,null) , b64encoder.toString() , myuser.username , users.length);
	function onResult (res : String ) : void {
		setTimeout(takeSnapShot , MyConfig.TIMER);	
	}
	
}

public function login():void {
	var validators:Array = Validator.validateAll([email_txtV,password_txtV]);
	if(validators.length>0) {
		return;
	}		
	myConfig.gateway.call("tv.login", new Responder(onResult,null),email_txt.text,password_txt.text);
    function onResult ( result : Object ) : void {
		if (result.ok==0) {
			Alert.show(result.message);
			return
		}
		myuser = new User(result.id , result.username , result.sex , result.online , result.webcam);
		myuser.email = result.email;
		myuser.room = result.username;
		myuser.channelTypeId = result.channelTypeId;
		myuser.channel = result.channel;
		myuser.description = result.description;
		myuser.canChat = result.canChat;
		myuser.password = result.password;
	
		currentState = "Live";
		loginAs();
    }
	
}

public function init():void {
	myConfig.gateway.call("tv.getWebcamConfig", new Responder(onResult,null) );
    function onResult ( result : Object ) : void {
    	MyConfig.CAMERA_FPS = result.fps;
    	MyConfig.CAMERA_WIDTH = result.w;
    	MyConfig.CAMERA_HEIGHT = result.h;
    	MyConfig.CAMERA_KEYFRAME = result.keyframe;
    	MyConfig.QAULITY = result.quality;
    	MyConfig.BW = result.BW;
    	MyConfig.maxUsers = result.maxUsers;
    	init2();
    }		
}
public function init2():void {
	var langue:String = Application.application.parameters.langue;
	if (!langue || langue=="") langue="en"
	getTraductions(langue);
	var room:String = Application.application.parameters.room;
	var canChat:String = Application.application.parameters.canChat;
	myuser = new User(1,"","",false,false);
	if (!room || room=="") {
		fillTypes();	
		camera = Camera.getCamera();
		if (camera.muted) Security.showSettings(SecurityPanel.DEFAULT);
		return;
	}
	if (canChat=="true") {
		currentState = "playchat";		
	}
	else {
		currentState = "play";	
	}	
	
	var myid:int = int(Math.random()*10000);
	var username:String = "user" + myid;
	
	myuser = new User(myid , username , "m", true , true);
	myuser.room = room;
	loginAs();

}

public function changeRoomClick():void {
	currentState="rooms";	
}

public function getBanned():void {
}
public function alertError(msg:String):void {
	var alert:Alert = new Alert();
	alert=Alert.show(msg,"",4,null,null,errorIcon);
	alert.styleName="rotateStyle";
}


private function OnSync(event:SyncEvent):void {
}
		
public function addUser(id:int , username:String , sex:String , online:Boolean , webcam:Boolean , room:String): void{ 
   	var obj:Object = new Object();
   	var trouve:Boolean;
    obj.id = id; 
    obj.username=username;
    obj.sex = sex; 
    obj.online=online;
    obj.webcam=webcam;
    obj.room = room;

    if (sex=="m") obj.icon=maleIcon;
    if (sex=="f") obj.icon=femaleIcon;
    if (sex=="c") obj.icon=coupleIcon;
    if (sex=="a") obj.icon=adminIcon;
    			    
	var i:int = getUserIndex(username);
	if (i>=0) return;
    users.addItem(obj);
    
}